#ifndef __SOCKET_H__
#define __SOCKET_H__

#include    <sys/types.h>
#include    <sys/socket.h>
#include    <netinet/in.h>
#include    <netdb.h>
#include    <unistd.h>
#include    <string>
#include    <arpa/inet.h>
#include    <errno.h>
#include    <netinet/in.h>
#include    <limits.h>
#include    <fcntl.h>
#include    <thread/Shared.h>

#include    "IOStream.h"

namespace MyUtil
{
using namespace std;

class InetAddress : public IceUtil::Shared
{
public:
    InetAddress(uint32_t host, uint16_t port);
    InetAddress(const string& host, uint16_t port);
    InetAddress(struct sockaddr& saddr);
    InetAddress(struct sockaddr_in& saddrin);

    static string toStringHost(uint32_t ipnet);
    static string toStringHost(struct sockaddr& saddr);
    static string toStringHost(struct sockaddr_in& saddrin);

    static uint32_t toInetHost(const string& host);
    static uint32_t toInetHost(struct sockaddr& saddr);
    static uint32_t toInetHost(struct sockaddr_in& saddrin);

    struct sockaddr_in* getSockAddrIn();
    struct sockaddr* getSockAddr();

    string getHostAsString();
    string strPort();
    uint32_t getHostAsInt();
    uint16_t getPort();
    uint16_t getInetPort();

private:
    struct sockaddr_in _sockaddr;
};
typedef IceUtil::Handle<InetAddress> InteAddressPtr;
	
//---------------------------------------------------------------------------
class SocketBasic : public FileDescriptor
{
public:
    SocketBasic();
	SocketBasic(int fd);
	virtual ~SocketBasic();
		
    int getOption(int key);
	void setOption(int key, int value);
	
	void setNonBlock(bool nonBlock);	
	void setLinger( bool isLinger );
};

//---------------------------------------------------------------------------
class Socket : public SocketBasic
{
public:
    Socket(int fd);
    Socket(const string& host, int port);
    
    virtual ~Socket();
	  
   	string getLocalHost();
    string getRemoteHost();
    uint16_t getLocalPort();
    uint16_t getRemotePort();  
private:
    //  Disallow to use
    Socket(const Socket& rhs);
    Socket& operator= (const Socket& rhs);    
};
typedef IceUtil::Handle<Socket> SocketPtr;
	
//---------------------------------------------------------------------------
class ServerSocket : public SocketBasic
{
public:
    ServerSocket(int port, int num = 200);
    virtual ~ServerSocket(void);
    
    SocketPtr accept();
    
private:
    //  Disallow to use
    ServerSocket(const ServerSocket& rhs);
    ServerSocket& operator=(const ServerSocket& rhs);
};
typedef IceUtil::Handle<ServerSocket> ServerSocketPtr;

//--------------------------------------------------------------------------
class SocketException : public IceUtil::Exception
{

};
 
};

#endif                                        // #ifndef
